package cn.jhz.learn.blog.test.impl;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;

import cn.jhz.learn.blog.po.photo.BlogPhoto;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import cn.jhz.learn.blog.common.exception.ParamException;
import cn.jhz.learn.blog.service.core.open.LabelService;
import cn.jhz.learn.blog.dao.BlogEntityLabelMapper;
import cn.jhz.learn.blog.dao.other.BlogLabelMapper;
import cn.jhz.learn.blog.po.search.BlogLabel;
import cn.jhz.learn.blog.po.BlogEntityLabel;

@Service("labelService")
public class LabelServiceImpl implements LabelService {


	private final BlogLabelMapper labelMapper;
	private final BlogEntityLabelMapper entityLabelMapper;
	
	private static final Function<String, BlogLabel> createBlogLabel = BlogLabel::new;
	private static final BiFunction<Integer, Integer, BlogEntityLabel> createBlogArticleLabel = BlogEntityLabel::new;
	
//	@Autowired
	public LabelServiceImpl(BlogLabelMapper labelMapper, BlogEntityLabelMapper entityLabelMapper) {
		this.labelMapper = labelMapper;
		this.entityLabelMapper = entityLabelMapper;
	}

	@Override
	public Optional<List<BlogEntityLabel>> batchAddArticleLabels(Integer articleId, Set<String> labelSet){
		return batchAddEntityLabels(articleId,labelSet,"blog_article_label");
	}

	@Override
	public Optional<List<BlogEntityLabel>> batchAddPhotosLabels(List<BlogPhoto> photoIdList, Set<String> labelSet) {
		return Optional.empty();
	}

	@Override
	public Optional<List<BlogEntityLabel>> batchModifyArticleLabels(Integer articleId, Set<String> labelSet) {
		return batchModifyEntityLabel(articleId, labelSet, "blog_article");
	}

	@Override
	public Optional<List<BlogEntityLabel>> batchModifyPhotosLabels(Set<Integer> photoIdSet, Set<String> labelSet) {
		return Optional.empty();
	}





	private Optional<List<BlogLabel>> batchAddLabel(Set<String> labelSet) {
		Set<String> titleSet = Optional.ofNullable(labelSet).orElseGet(Sets::newHashSet);
		List<BlogLabel> isExistLabels = Lists.newArrayList();
		String errorLabelsStr;

		if(!titleSet.isEmpty()) {
			isExistLabels.addAll(labelMapper.selectByTitleSet(titleSet));
			errorLabelsStr = isExistLabels.stream()
					.filter(label->label.getStatus().equals(0))
					.map(BlogLabel::getTitle)
					.collect(joining("、","不合法标签: [","]！"));
			//无效标签集合
			if(errorLabelsStr.contains("、"))
				throw new ParamException(errorLabelsStr);

			titleSet.removeAll(isExistLabels.stream().map(BlogLabel::getTitle).collect(toList()));
			if(!titleSet.isEmpty()) {
				List<BlogLabel> newLabels = titleSet.stream().map(createBlogLabel::apply).collect(toList());
				labelMapper.batchInsert(newLabels);
				//TODO:SysInfo

				isExistLabels.addAll(newLabels);
			}
		}

		return Optional.ofNullable(isExistLabels);
	}

	private Optional<List<BlogEntityLabel>> batchAddEntitiesLabels(List<Integer> photoIdList, Set<String> labelSet){
		return Optional.empty();
	}

	private Optional<List<BlogEntityLabel>> batchAddEntityLabels(Integer id, Set<String> labelSet,
																 String tableName){
		Integer entityId = Optional.ofNullable(id).orElseThrow(ExceptionConstant.paramArticleTitleIsNull);
		Set<String> titleSet = Optional.ofNullable(labelSet).orElseGet(Sets::newHashSet);
		List<BlogEntityLabel> toModifyEntityLabelList = Lists.newArrayList();

		if(!titleSet.isEmpty()) {
			toModifyEntityLabelList = batchAddLabel(labelSet).orElseGet(Lists::newArrayList).stream()
					.map(label->createBlogArticleLabel.apply(entityId, label.getId()))
					.collect(toList());
			entityLabelMapper.insertListSelective(toModifyEntityLabelList, tableName);
			//TODO:SysInfo
		}
		return Optional.ofNullable(toModifyEntityLabelList);
	}

	private Optional<List<BlogEntityLabel>> batchModifyEntityLabel(Integer id, Set<String> labelSet, String tableName) {
		Integer entityId = Optional.ofNullable(id).orElseThrow(ExceptionConstant.paramArticleTitleIsNull);
		Set<String> titleSet = Optional.ofNullable(labelSet).orElseGet(Sets::newHashSet);
		List<BlogEntityLabel> toModifyEntityLabelList = Lists.newArrayList();

		if(!titleSet.isEmpty()) {
			entityLabelMapper.updateStatusByIdAndTitles(entityId, titleSet);
			toModifyEntityLabelList = batchAddLabel(labelSet).orElseGet(Lists::newArrayList).stream()
					.map(label->createBlogArticleLabel.apply(entityId, label.getId()))
					.collect(toList());
			entityLabelMapper.insertListSelective(toModifyEntityLabelList, tableName);
			//TODO:SysInfo
		}

		return Optional.ofNullable(toModifyEntityLabelList);
	}

	private Optional<List<BlogEntityLabel>> batchRemoveEntityLabelById(Integer entityLabelId) {return Optional.empty();}

}